<template>
  <div class="app-detail-page">
    <!-- 顶部导航栏 -->
    <div class="top-bar">
      <div class="left-section">
        <div class="app-info">
          <div class="app-title-row">
            <h1 class="app-name">{{ getAppDisplayName() }}</h1>
            <a-tag v-if="shouldShowStatusTag()" :color="getStatusColor()" class="app-status-tag">
              <template #icon>
                <component :is="getStatusIcon()" />
              </template>
              {{ getAppStatus() }}
            </a-tag>
          </div>
          <div class="app-meta">
            <span v-if="shouldShowTypeTag()" class="app-type">
              {{ getAppTypeLabel() }}
            </span>
            <span class="create-time">{{ formatTime(appInfo?.createTime) }}</span>
          </div>
        </div>
      </div>
      <div class="right-section">
        <a-space>
          <a-button @click="showDetailModal" class="detail-btn">
            <template #icon>
              <InfoCircleOutlined />
            </template>
            应用详情
          </a-button>
          <a-button
            type="primary"
            @click="handleDeploy"
            :loading="isDeploying"
            :disabled="!canDeploy"
            class="deploy-btn"
          >
            <template #icon>
              <CloudUploadOutlined />
            </template>
            {{ appInfo?.deployKey ? '重新部署' : '部署应用' }}
          </a-button>
          <a-dropdown placement="bottomRight">
            <a-button class="more-btn">
              <template #icon>
                <MoreOutlined />
              </template>
            </a-button>
            <template #overlay>
              <a-menu>
                <a-menu-item @click="downloadCode">
                  <template #icon>
                    <DownloadOutlined />
                  </template>
                  下载代码
                </a-menu-item>
                <a-menu-divider />
                <a-menu-item @click="goToMyApps">
                  <template #icon>
                    <ArrowLeftOutlined />
                  </template>
                  返回列表
                </a-menu-item>
              </a-menu>
            </template>
          </a-dropdown>
        </a-space>
      </div>
    </div>

    <!-- 主要内容区域 -->
    <div class="main-content">
      <!-- 左侧对话区域 -->
      <div
        class="chat-section"
        :class="{ dragging: isDragging }"
        :style="{ width: `${leftWidth}%` }"
      >
        <!-- 消息区域 -->
        <div class="messages-container" ref="messagesRef" @scroll="handleScroll">
          <!-- 加载更多按钮 -->
          <div v-if="hasMoreHistory" class="load-more-wrapper">
            <a-button
              type="text"
              @click="loadMoreHistory"
              :loading="isLoadingHistory"
              class="load-more-btn"
            >
              <template #icon>
                <UpOutlined />
              </template>
              加载更多历史消息
            </a-button>
          </div>

          <!-- 消息列表 -->
          <div class="messages-list">
            <div
              v-for="(message, index) in messages"
              :key="message.id || index"
              class="message-item"
              :class="{
                'user-message': message.messageType === 'user',
                'ai-message': message.messageType === 'assistant' || message.messageType === 'ai',
              }"
            >
              <div class="message-avatar">
                <a-avatar
                  v-if="message.messageType === 'user'"
                  :size="36"
                  class="user-avatar"
                  :src="loginUserStore.loginUser.userAvatar"
                >
                  <template #icon>
                    <UserOutlined />
                  </template>
                </a-avatar>
                <a-avatar
                  v-else-if="message.messageType === 'assistant' || message.messageType === 'ai'"
                  :size="36"
                  class="ai-avatar"
                >
                  <template #icon>
                    <AndroidOutlined />
                  </template>
                </a-avatar>
                <a-avatar v-else :size="36" class="ai-avatar">
                  <template #icon>
                    <AndroidOutlined />
                  </template>
                </a-avatar>
              </div>
              <div class="message-content">
                <div class="message-header">
                  <span class="sender-name">
                    {{
                      message.messageType === 'user'
                        ? loginUserStore.loginUser.userName || '我'
                        : 'AI 助手'
                    }}
                  </span>
                  <span class="message-time">{{ formatMessageTime(message.createTime) }}</span>
                </div>
                <div class="message-text">
                  <!-- AI消息：支持Markdown渲染（包括历史消息和实时消息） -->
                  <div
                    v-if="message.messageType === 'assistant' || message.messageType === 'ai'"
                    class="ai-message-content"
                  >
                    <MarkdownRenderer
                      :content="message.message"
                      :is-streaming="message.isStreaming"
                    />
                    <span v-if="message.isStreaming" class="typing-cursor">|</span>
                  </div>
                  <!-- 用户消息：纯文本 -->
                  <div v-else>{{ message.message }}</div>
                </div>
              </div>
            </div>
          </div>

          <!-- 空状态 -->
          <div v-if="messages.length === 0 && !isGenerating" class="empty-messages">
            <div class="empty-content">
              <AndroidOutlined class="empty-icon" />
              <p>开始与 AI 对话，完善你的应用</p>
            </div>
          </div>
        </div>

        <!-- 输入区域 -->
        <div class="input-section">
          <div class="input-container">
            <!-- 选中元素提示 -->
            <a-alert
              v-if="selectedElement"
              type="info"
              show-icon
              :message="selectedElementTitle"
              closable
              @close="clearSelectedElement"
              style="margin-bottom: 8px"
            >
              <template #description>
                <div class="selected-el-desc">
                  <div class="row">
                    <span class="label">selector</span>
                    <code class="code">{{ selectedElement?.selector }}</code>
                  </div>
                  <div class="row" v-if="selectedClassString">
                    <span class="label">class</span>
                    <code class="code">{{ selectedClassString }}</code>
                  </div>
                  <div class="row" v-if="selectedHasText">
                    <span class="label">内容</span>
                    <span class="content">{{ selectedElement?.textSnippet }}</span>
                  </div>
                  <div class="row" v-if="selectedElement?.pagePath">
                    <span class="label">页面路径</span>
                    <code class="code">{{ selectedElement?.pagePath }}</code>
                  </div>
                </div>
              </template>
            </a-alert>
            <a-textarea
              v-model:value="currentMessage"
              placeholder="描述你想要的功能改进..."
              :rows="3"
              :maxlength="1000"
              :auto-size="{ minRows: 3, maxRows: 6 }"
              class="message-input"
              @keydown="handleKeyDown"
              :disabled="isGenerating"
            />
            <div class="input-actions">
              <div class="char-count">{{ currentMessage.length }}/1000</div>
              <div class="button-group">
                <a-button
                  @click="toggleEditMode"
                  :type="isEditMode ? 'primary' : 'default'"
                  :ghost="isEditMode"
                  :disabled="!previewUrl || isGenerating"
                  class="edit-btn"
                >
                  {{ isEditMode ? '退出编辑' : '编辑' }}
                </a-button>
                <a-button
                  type="primary"
                  @click="() => sendMessage()"
                  :loading="isGenerating"
                  :disabled="!currentMessage.trim() || isGenerating"
                  class="send-btn"
                >
                  <template #icon>
                    <SendOutlined />
                  </template>
                  发送
                </a-button>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- 分割条 -->
      <div class="splitter" @mousedown="startDrag" :class="{ dragging: isDragging }"></div>

      <!-- 右侧预览区域 -->
      <div
        class="preview-section"
        :class="{ dragging: isDragging }"
        :style="{ width: `${rightWidth}%` }"
      >
        <div class="preview-header">
          <h3>应用预览</h3>
          <div class="preview-actions">
            <a-button
              type="text"
              @click="refreshPreview"
              :loading="isRefreshing"
              class="refresh-btn"
            >
              <template #icon>
                <ReloadOutlined />
              </template>
            </a-button>
            <a-button type="text" @click="openInNewTab" class="external-btn">
              <template #icon>
                <LinkOutlined />
              </template>
            </a-button>
          </div>
        </div>
        <div class="preview-content">
          <div v-if="!previewUrl" class="preview-placeholder">
            <div class="placeholder-content">
              <CodeOutlined class="placeholder-icon" />
              <p>应用生成完成后将在此处显示预览</p>
              <p class="placeholder-hint">与AI对话完善你的应用功能</p>
            </div>
          </div>
          <iframe
            v-else
            :src="previewUrl"
            class="preview-iframe"
            frameborder="0"
            @load="handleIframeLoad"
            ref="previewIframeRef"
          ></iframe>
          <!-- 拖拽时的遮罩层，防止iframe捕获鼠标事件 -->
          <div v-if="isDragging" class="drag-overlay"></div>
          <div v-if="isGenerating" class="generating-overlay">
            <a-spin size="large" />
            <p>AI 正在生成代码中...</p>
          </div>
        </div>
      </div>
    </div>

    <!-- 应用详情弹窗 -->
    <a-modal
      v-model:open="detailModalVisible"
      title="应用详情"
      width="800px"
      :footer="null"
      class="app-detail-modal"
    >
      <div class="detail-content" v-if="appInfo">
        <a-descriptions :column="1" bordered>
          <a-descriptions-item label="应用名称">
            <span class="app-name-text">{{ appInfo.appName || '未命名应用' }}</span>
          </a-descriptions-item>
          <a-descriptions-item label="应用分类" v-if="appInfo.appCategory">
            <a-tag color="purple">{{ appInfo.appCategory }}</a-tag>
          </a-descriptions-item>
          <a-descriptions-item label="代码类型">
            <a-tag color="green">{{ getAppTypeLabel() || '未知类型' }}</a-tag>
          </a-descriptions-item>
          <a-descriptions-item label="创建者">
            {{ appInfo.userName || '未知用户' }}
          </a-descriptions-item>
          <a-descriptions-item label="创建时间">
            {{ formatDetailTime(appInfo.createTime) }}
          </a-descriptions-item>
          <a-descriptions-item label="更新时间">
            {{ formatDetailTime(appInfo.updateTime) }}
          </a-descriptions-item>
          <a-descriptions-item label="部署状态">
            <a-tag :color="getStatusColor()">
              <template #icon>
                <component :is="getStatusIcon()" />
              </template>
              {{ getAppStatus() }}
            </a-tag>
          </a-descriptions-item>
          <a-descriptions-item label="预览地址" v-if="deployUrl">
            <a :href="deployUrl" target="_blank" class="preview-link">
              <LinkOutlined />
              {{ deployUrl }}
            </a>
          </a-descriptions-item>
          <a-descriptions-item label="应用描述" v-if="appInfo.appDescription">
            <div class="app-description">{{ appInfo.appDescription }}</div>
          </a-descriptions-item>
          <a-descriptions-item label="初始提示词" v-if="appInfo.initPrompt">
            <div class="init-prompt">{{ appInfo.initPrompt }}</div>
          </a-descriptions-item>
        </a-descriptions>

        <!-- 统计信息 -->
        <div class="stats-section">
          <h4>统计信息</h4>
          <a-row :gutter="16">
            <a-col :span="8">
              <a-statistic title="对话消息数" :value="messages.length" />
            </a-col>
            <a-col :span="8">
              <a-statistic title="用户消息数" :value="userMessageCount" />
            </a-col>
            <a-col :span="8">
              <a-statistic title="AI回复数" :value="aiMessageCount" />
            </a-col>
          </a-row>
        </div>
      </div>
    </a-modal>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, onUnmounted, nextTick, computed } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { message } from 'ant-design-vue'
import {
  ArrowLeftOutlined,
  CloudUploadOutlined,
  MoreOutlined,
  LinkOutlined,
  DownloadOutlined,
  UserOutlined,
  AndroidOutlined,
  SendOutlined,
  ReloadOutlined,
  CodeOutlined,
  UpOutlined,
  CheckCircleOutlined,
  SyncOutlined,
  ExclamationCircleOutlined,
  InfoCircleOutlined,
} from '@ant-design/icons-vue'
import { getAppVoById, chatToGenCode, deployApp, downloadAppCode } from '@/api/appController'
import { listAppChatHistory } from '@/api/chatHistoryController'
import { useLoginUserStore } from '@/stores/useLoginUserStore'
import { getStaticPreviewUrl, getDeployUrl, API_BASE_URL } from '@/env'
import { setupIframeEditor, type SelectedElementInfo } from '@/utils/iframeEditor'
import MarkdownRenderer from '@/components/MarkdownRenderer.vue'
import { log } from 'console'

const router = useRouter()
const route = useRoute()
const loginUserStore = useLoginUserStore()

// 扩展AppVO类型
interface ExtendedAppVO extends API.AppVO {}

// 扩展消息类型
interface ExtendedChatHistory extends API.ChatHistory {
  isStreaming?: boolean
}

// 响应式数据
const appInfo = ref<ExtendedAppVO>()
const messages = ref<Array<ExtendedChatHistory>>([])
const currentMessage = ref('')
const isGenerating = ref(false)
const isDeploying = ref(false)
const isLoadingHistory = ref(false)
const hasMoreHistory = ref(false)
const isRefreshing = ref(false)
const previewUrl = ref('')
const deployUrl = ref('')
const messagesRef = ref<HTMLElement>()
const oldestCreateTime = ref<string>()
const previewIframeRef = ref<HTMLIFrameElement>()

// 应用详情弹窗
const detailModalVisible = ref(false)

// 滚动控制相关
const userHasScrolled = ref(false)
const isAtBottom = ref(true)
const scrollTimeout = ref<number | null>(null)

// 可视化编辑
const isEditMode = ref(false)
const selectedElement = ref<SelectedElementInfo | null>(null)
let editorController: ReturnType<typeof setupIframeEditor> | null = null
const isSameOrigin = computed(() => {
  try {
    if (!previewUrl.value) return false
    const u = new URL(previewUrl.value, window.location.href)
    return u.origin === window.location.origin
  } catch {
    return false
  }
})
const selectedClassString = computed(() => {
  const t = selectedElement.value
  if (!t || !t.classList || t.classList.length === 0) return ''
  return t.classList.join(' ')
})
const selectedHasText = computed(() => {
  const t = selectedElement.value
  const mediaTags = ['img', 'video', 'audio', 'canvas', 'iframe', 'svg']
  return !!(t && t.textSnippet && t.textSnippet.trim() && !mediaTags.includes(t.tagName))
})
const selectedElementTitle = computed(() => {
  if (!selectedElement.value) return ''
  const t = selectedElement.value
  return `已选中元素：${t.tagName}${t.id ? '#' + t.id : ''}`
})
const selectedElementDesc = computed(() => {
  if (!selectedElement.value) return ''
  const t = selectedElement.value
  const cls = t.classList && t.classList.length ? '.' + t.classList.join('.') : ''
  const mediaTags = ['img', 'video', 'audio', 'canvas', 'iframe', 'svg']
  const showText = t.textSnippet && t.textSnippet.trim() && !mediaTags.includes(t.tagName)
  const base = `selector: ${t.selector || ''}${cls ? '  class: ' + cls : ''}`
  return showText ? `${base}\n内容: ${t.textSnippet}` : base
})

const clearSelectedElement = () => {
  selectedElement.value = null
}

const ensureEditor = () => {
  const iframe = previewIframeRef.value as HTMLIFrameElement
  if (!iframe) return
  if (!editorController) {
    editorController = setupIframeEditor({
      iframe,
      previewUrl: previewUrl.value,
      onHoverChange: () => {},
      onSelect: (info) => {
        selectedElement.value = info
      },
    })
  }
}

const toggleEditMode = () => {
  ensureEditor()
  if (!editorController) return
  if (isEditMode.value) {
    editorController.disable()
    isEditMode.value = false
    // 退出编辑模式时清除选中的元素
    selectedElement.value = null
  } else {
    if (!isSameOrigin.value) {
      message.warning(
        '预览页面与当前站点非同源，无法自动注入高亮脚本。请在子页面注入上报脚本或调整为同源。',
      )
      console.warn('[可视化编辑] 非同源：', previewUrl.value, ' vs ', window.location.origin)
    }
    editorController.enable()
    isEditMode.value = true
  }
}

// 分割条拖拽相关
const leftWidth = ref(50)
const rightWidth = computed(() => 100 - leftWidth.value)
const isDragging = ref(false)
const startX = ref(0)
const startLeftWidth = ref(50)
// 添加动画帧ID用于优化拖拽性能
let animationFrameId: number | null = null
// 添加拖拽缓存，减少不必要的更新
let dragCache = {
  lastWidth: 50,
  lastUpdateTime: 0,
}

// 计算属性
const appId = route.params.id
const canDeploy = computed(() => messages.value.length >= 2 && !isGenerating.value)

// 消息统计
const userMessageCount = computed(
  () => messages.value.filter((msg) => msg.messageType === 'user').length,
)
const aiMessageCount = computed(
  () =>
    messages.value.filter((msg) => msg.messageType === 'assistant' || msg.messageType === 'ai')
      .length,
)

// 获取应用状态
const getAppStatus = () => {
  if (isGenerating.value) return '生成中'
  if (appInfo.value?.deployKey) return '已部署'
  if (messages.value.length < 2) return '开发中'
  return '待部署'
}

// 获取状态颜色
const getStatusColor = () => {
  if (isGenerating.value) return 'processing'
  if (appInfo.value?.deployKey) return 'success'
  if (messages.value.length < 2) return 'default'
  return 'warning'
}

// 获取状态图标
const getStatusIcon = () => {
  if (isGenerating.value) return SyncOutlined
  if (appInfo.value?.deployKey) return CheckCircleOutlined
  if (messages.value.length < 2) return CodeOutlined
  return ExclamationCircleOutlined
}

// 获取应用显示名称
const getAppDisplayName = () => {
  if (!appInfo.value) return '加载中...'
  if (appInfo.value.appName) return appInfo.value.appName
  if (isGenerating.value) return '应用生成中...'
  return '未命名应用'
}

// 是否显示状态标签
const shouldShowStatusTag = () => {
  // 只有当应用有名称时才显示状态标签（表示应用已完成基本生成）
  return appInfo.value?.appName && appInfo.value.appName.trim() !== ''
}

// 是否显示类型标签
const shouldShowTypeTag = () => {
  // 只有当应用有名称和类型时才显示类型标签
  return (
    appInfo.value?.appName &&
    appInfo.value.appName.trim() !== '' &&
    appInfo.value?.codeGenType &&
    appInfo.value.codeGenType.trim() !== ''
  )
}

// 获取应用类型标签
const getAppTypeLabel = () => {
  if (!appInfo.value?.codeGenType) {
    return ''
  }
  const typeMap = {
    html: 'HTML',
    multi_file: '多文件',
    vue_project: 'Vue项目',
  }
  return typeMap[appInfo.value.codeGenType] || appInfo.value.codeGenType
}

// 格式化消息时间（简短格式）
const formatMessageTime = (timeStr?: string) => {
  if (!timeStr) return ''
  const date = new Date(timeStr)
  const now = new Date()
  const diff = now.getTime() - date.getTime()
  const minutes = Math.floor(diff / (1000 * 60))

  if (minutes < 1) return '刚刚'
  if (minutes < 60) return `${minutes}分钟前`
  if (minutes < 1440) return `${Math.floor(minutes / 60)}小时前`

  return date.toLocaleString('zh-CN', {
    month: 'numeric',
    day: 'numeric',
    hour: '2-digit',
    minute: '2-digit',
  })
}

// 返回我的应用页面
const goToMyApps = () => {
  router.push('/my/apps')
}

// 显示应用详情弹窗
const showDetailModal = () => {
  detailModalVisible.value = true
}

// 格式化详细时间（用于弹窗显示）
const formatDetailTime = (timeStr?: string) => {
  if (!timeStr) return '未知'
  const date = new Date(timeStr)
  return date.toLocaleString('zh-CN', {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit',
  })
}

// 格式化时间
const formatTime = (timeStr?: string) => {
  if (!timeStr) return ''
  const date = new Date(timeStr)
  const now = new Date()
  const diff = now.getTime() - date.getTime()
  const minutes = Math.floor(diff / (1000 * 60))

  if (minutes < 1) return '刚刚'
  if (minutes < 60) return `${minutes}分钟前`
  if (minutes < 1440) return `${Math.floor(minutes / 60)}小时前`

  return date.toLocaleString('zh-CN', {
    month: 'numeric',
    day: 'numeric',
    hour: '2-digit',
    minute: '2-digit',
  })
}

// 获取应用信息
const fetchAppInfo = async () => {
  try {
    const res = await getAppVoById({ id: appId })
    if (res.data.code === 0) {
      appInfo.value = res.data.data

      // 设置预览URL
      if (appInfo.value?.codeGenType) {
        deployUrl.value = getDeployUrl(res.data.data.deployKey)
        previewUrl.value = getStaticPreviewUrl(appInfo.value.codeGenType, appId.toString())
        console.log('设置预览URL:', previewUrl.value)
      }
    } else {
      message.error('获取应用信息失败：' + res.data.message)
      router.push('/')
    }
  } catch (error) {
    console.error('获取应用信息失败:', error)
    message.error('获取应用信息失败')
    router.push('/')
  }
}

// 加载聊天历史
const loadChatHistory = async (isLoadMore = false) => {
  try {
    if (isLoadMore) {
      isLoadingHistory.value = true
    }

    const params: API.listAppChatHistoryParams = {
      appId: appId,
      pageSize: 10,
    }

    if (isLoadMore && oldestCreateTime.value) {
      params.lastCreateTime = oldestCreateTime.value
    }

    const res = await listAppChatHistory(params)

    if (res.data.code === 0) {
      const newMessages = res.data.data?.records || []

      // 将消息按时间正序排列（老消息在前，新消息在后）
      const sortedMessages = [...newMessages].sort(
        (a, b) => new Date(a.createTime).getTime() - new Date(b.createTime).getTime(),
      )

      if (isLoadMore) {
        // 加载更多时，将历史消息插入到开头
        messages.value.unshift(...sortedMessages)
      } else {
        // 首次加载，直接设置消息列表
        messages.value = sortedMessages
      }

      // 更新最早时间和是否还有更多数据
      if (newMessages.length > 0) {
        // 找到最早的消息时间
        const earliestMessage = sortedMessages[0]
        oldestCreateTime.value = earliestMessage.createTime
        hasMoreHistory.value = newMessages.length === 10
      } else {
        hasMoreHistory.value = false
      }

      // 首次加载后滚动到底部显示最新消息
      if (!isLoadMore) {
        nextTick(() => {
          scrollToBottom()
        })
      }

      // 如果是首次加载且没有历史消息，且是用户自己的应用，自动发送初始消息
      if (
        !isLoadMore &&
        messages.value.length === 0 &&
        appInfo.value?.userId === loginUserStore.loginUser.id &&
        appInfo.value?.initPrompt
      ) {
        await sendMessage(appInfo.value.initPrompt)
      }
    }
  } catch (error) {
    console.error('加载聊天历史失败:', error)
    message.error('加载聊天历史失败')
  } finally {
    if (isLoadMore) {
      isLoadingHistory.value = false
    }
  }
}

// 加载更多历史
const loadMoreHistory = () => {
  loadChatHistory(true)
}

// 检查是否在底部
const checkIfAtBottom = () => {
  if (!messagesRef.value) return true

  const { scrollTop, scrollHeight, clientHeight } = messagesRef.value
  // 允许5px的误差
  const threshold = 5
  return scrollHeight - scrollTop - clientHeight <= threshold
}

// 处理用户滚动事件
const handleScroll = () => {
  if (!messagesRef.value) return

  // 清除之前的超时
  if (scrollTimeout.value) {
    clearTimeout(scrollTimeout.value)
  }

  // 检查是否在底部
  isAtBottom.value = checkIfAtBottom()

  // 标记用户已经滚动过
  userHasScrolled.value = true

  // 设置超时，如果用户停止滚动一段时间后重置标记
  scrollTimeout.value = setTimeout(() => {
    // 如果用户滚动到底部，重置用户滚动标记
    if (isAtBottom.value) {
      userHasScrolled.value = false
    }
  }, 1000) // 1秒后重置
}

// 智能滚动到底部
const scrollToBottom = async (force = false) => {
  await nextTick()
  if (!messagesRef.value) return

  // 如果强制滚动，或者用户没有手动滚动过，或者用户当前在底部，则滚动到底部
  if (force || !userHasScrolled.value || isAtBottom.value) {
    messagesRef.value.scrollTop = messagesRef.value.scrollHeight
    isAtBottom.value = true
    // 如果是自动滚动，不要标记为用户滚动
    if (!force) {
      userHasScrolled.value = false
    }
  }
}

// 发送消息
const sendMessage = async (messageText?: string) => {
  // 确保参数是字符串类型，过滤掉事件对象
  let text: string
  if (typeof messageText === 'string') {
    text = messageText.trim()
  } else {
    text = currentMessage.value.trim()
  }

  if (!text || isGenerating.value) return

  // 如有选中元素，增强提示词
  if (selectedElement.value) {
    const el = selectedElement.value
    const extra = `\n[选中元素]\nselector: ${el.selector || ''}\ntag: ${el.tagName}${el.id ? '#' + el.id : ''}\nclass: ${(el.classList || []).join(' ')}\npagePath: ${el.pagePath || ''}\nmargin: ${el.styles?.marginTop} ${el.styles?.marginRight} ${el.styles?.marginBottom} ${el.styles?.marginLeft}\nborderRadius: ${el.styles?.borderRadius}`
    text = `${text}\n\n${extra}`
  }

  // 立即清空输入框和清除选中元素（无论发送成功与否）
  if (typeof messageText !== 'string') {
    currentMessage.value = ''
  }
  // 发送消息时立即清除选中的元素
  selectedElement.value = null

  // 添加用户消息到列表末尾
  const userMessage: API.ChatHistory = {
    id: Date.now(),
    message: text,
    messageType: 'user',
    appId: appId,
    userId: loginUserStore.loginUser.id,
    createTime: new Date().toISOString(),
  }

  messages.value.push(userMessage)

  // 添加AI消息占位符到列表末尾
  const aiMessageId = Date.now() + 1
  const aiMessage: ExtendedChatHistory = {
    id: aiMessageId,
    message: '',
    messageType: 'assistant',
    appId: appId,
    createTime: new Date().toISOString(),
    isStreaming: true,
  }

  messages.value.push(aiMessage)
  isGenerating.value = true

  // 发送消息时重置滚动状态，确保能够自动滚动
  userHasScrolled.value = false
  isAtBottom.value = true

  await scrollToBottom()

  try {
    // 创建SSE连接
    const sseUrl = `${API_BASE_URL}/app/chat/gen/code?appId=${appId}&message=${encodeURIComponent(text)}`
    console.log('创建SSE连接:', sseUrl)

    const eventSource = new EventSource(sseUrl, {
      withCredentials: true,
    })

    // 用于存储完整的流式数据
    let fullStreamData = ''
    // 用于存储当前显示的数据（打字机效果）
    let displayedData = ''
    // 打字机效果定时器
    let typewriterTimer: number | null = null

    // 打字机效果函数
    const startTypewriterEffect = () => {
      if (typewriterTimer) {
        clearInterval(typewriterTimer)
      }

      const messageIndex = messages.value.findIndex((msg) => msg.id === aiMessageId)
      if (messageIndex === -1) return

      // 如果当前显示的数据已经等于完整数据，不需要启动打字机效果
      if (displayedData.length >= fullStreamData.length) {
        return
      }

      typewriterTimer = setInterval(() => {
        if (displayedData.length < fullStreamData.length) {
          // 逐字符显示，但可以一次显示多个字符以提高速度
          const charsToAdd = Math.min(2, fullStreamData.length - displayedData.length)
          displayedData = fullStreamData.substring(0, displayedData.length + charsToAdd)

          // 更新消息内容
          messages.value[messageIndex].message = displayedData
          messages.value = [...messages.value]

          // 智能滚动到底部
          nextTick(() => {
            scrollToBottom()
          })
        } else {
          // 打字机效果完成
          if (typewriterTimer) {
            clearInterval(typewriterTimer)
            typewriterTimer = null
          }
        }
      }, 15) // 每15ms显示字符，可以调整速度
    }

    eventSource.onopen = () => {
      console.log('SSE连接已建立')
    }

    eventSource.onmessage = (event) => {
      try {
        const data = event.data
        console.log('收到SSE数据:', data)

        // 跳过空数据
        if (!data || data.trim() === '') {
          return
        }

        // 处理SSE数据格式：data:{"data":"内容"}
        if (data.startsWith('data:')) {
          try {
            const jsonStr = data.substring(5) // 移除 "data:" 前缀
            const parsedData = JSON.parse(jsonStr)
            console.log('解析后的数据:', parsedData)

            // 处理流式数据：{data: "内容"}
            if (parsedData.data) {
              const messageContent = parsedData.data
              fullStreamData += messageContent
              console.log(`收到流式数据: "${messageContent}"`)
              console.log(`当前完整内容长度: ${fullStreamData.length}`)
              console.log(`当前完整内容: "${fullStreamData}"`)

              // 启动打字机效果
              startTypewriterEffect()
            }
          } catch (parseError) {
            console.log('JSON解析失败，跳过此数据块:', data)
          }
        } else {
          // 尝试直接解析JSON格式的流式数据
          try {
            const parsedData = JSON.parse(data)
            console.log('解析后的数据:', parsedData)

            // 处理流式数据：{data: "内容"}
            if (parsedData.data) {
              const messageContent = parsedData.data
              fullStreamData += messageContent
              console.log(`收到流式数据: "${messageContent}"`)
              console.log(`当前完整内容长度: ${fullStreamData.length}`)
              console.log(`当前完整内容: "${fullStreamData}"`)

              // 启动打字机效果
              startTypewriterEffect()
            }
          } catch (parseError) {
            console.log('JSON解析失败，跳过此数据块:', data)
          }
        }
      } catch (error) {
        console.error('处理SSE消息时出错:', error)
      }
    }

    // 监听done事件（正常结束）
    eventSource.addEventListener('done', async (event) => {
      console.log('收到done事件，流式传输正常结束')
      eventSource.close()

      // 确保打字机效果完成
      if (typewriterTimer) {
        clearInterval(typewriterTimer)
        typewriterTimer = null
      }

      // 确保显示完整内容
      const messageIndex = messages.value.findIndex((msg) => msg.id === aiMessageId)
      if (messageIndex !== -1) {
        messages.value[messageIndex].message = fullStreamData
        messages.value[messageIndex].isStreaming = false
        messages.value = [...messages.value]
      }
      isGenerating.value = false

      // 重置编辑模式与选中状态
      isEditMode.value = false
      editorController?.disable()
      selectedElement.value = null

      // 流式生成结束后重新获取应用信息（AI可能已经设置了应用名称和类型）
      try {
        console.log('流式生成结束，重新获取应用信息...')
        await fetchAppInfo()
        console.log('应用信息更新完成')
      } catch (error) {
        console.error('更新应用信息失败:', error)
      }

      // 生成完成后强制滚动到底部并刷新预览
      nextTick(() => {
        scrollToBottom(true) // 强制滚动
      })

      setTimeout(() => {
        refreshPreview()
      }, 1000)
    })

    eventSource.onerror = async (error) => {
      console.error('SSE连接错误:', error)
      console.log('当前连接状态:', eventSource.readyState)

      eventSource.close()

      // 停止打字机效果
      if (typewriterTimer) {
        clearInterval(typewriterTimer)
        typewriterTimer = null
      }

      // 更新AI消息状态
      const messageIndex = messages.value.findIndex((msg) => msg.id === aiMessageId)
      if (messageIndex !== -1) {
        const currentMessage = messages.value[messageIndex].message
        messages.value[messageIndex].isStreaming = false
        if (!currentMessage || currentMessage.trim() === '') {
          messages.value[messageIndex].message = '抱歉，生成过程中出现了错误，请稍后重试。'
        }
        messages.value = [...messages.value]
      }
      isGenerating.value = false

      // 即使出错也尝试更新应用信息（可能已经部分生成）
      try {
        console.log('SSE出错后尝试更新应用信息...')
        await fetchAppInfo()
      } catch (updateError) {
        console.error('更新应用信息失败:', updateError)
      }

      message.error('生成过程中出现错误，请检查网络连接')
    }
  } catch (error) {
    console.error('发送消息失败:', error)

    // 停止打字机效果
    if (typewriterTimer) {
      clearInterval(typewriterTimer)
      typewriterTimer = null
    }

    // 更新AI消息状态
    const messageIndex = messages.value.findIndex((msg) => msg.id === aiMessageId)
    if (messageIndex !== -1) {
      messages.value[messageIndex].isStreaming = false
      messages.value[messageIndex].message = '抱歉，发送消息失败，请稍后重试。'
      messages.value = [...messages.value]
    }
    isGenerating.value = false
    message.error('发送消息失败')

    // 确保即使发送失败也清空输入框
    if (typeof messageText !== 'string') {
      currentMessage.value = ''
    }
  }
}

// 处理键盘事件
const handleKeyDown = (e: KeyboardEvent) => {
  if (e.key === 'Enter' && !e.shiftKey) {
    e.preventDefault()
    sendMessage()
  }
}

// 部署应用
const handleDeploy = async () => {
  if (!canDeploy.value) return

  isDeploying.value = true
  try {
    const res = await deployApp({ appId: appId })
    console.log('部署接口完整响应:', res.data)

    if (res.data.code === 0) {
      message.success('部署成功！')

      // 重新获取应用信息
      await fetchAppInfo()
    } else {
      message.error('部署失败：' + res.data.message)
    }
  } catch (error) {
    console.error('部署失败:', error)
    message.error('部署失败，请稍后重试')
  } finally {
    isDeploying.value = false
  }
}

// 下载代码
const downloadCode = async () => {
  try {
    // 权限检查：只有应用创建者可以下载
    if (appInfo.value?.userId !== loginUserStore.loginUser.id) {
      message.error('无权限下载该应用代码')
      return
    }

    // 检查应用是否存在代码
    if (!appInfo.value?.codeGenType || !appInfo.value?.id) {
      message.error('应用代码不存在，请先生成代码')
      return
    }

    console.log('开始下载应用代码，appId:', appId)

    // 调用API接口下载（配置为blob响应类型）
    const response = await downloadAppCode(
      { appId: appId },
      {
        responseType: 'blob',
        getResponse: true, // 获取完整响应对象
      },
    )

    // 处理文件下载
    let blob: Blob
    let fileName = `${appInfo.value?.appName || appId}.zip`

    if (response.data instanceof Blob) {
      blob = response.data

      // 尝试从响应头获取文件名
      const contentDisposition = response.headers?.['content-disposition']
      if (contentDisposition) {
        const fileNameMatch = contentDisposition.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/)
        if (fileNameMatch && fileNameMatch[1]) {
          fileName = fileNameMatch[1].replace(/['"]/g, '') + '.zip'
        }
      }
    } else {
      // 兼容处理：如果不是blob，创建一个blob
      blob = new Blob([response.data || response], { type: 'application/zip' })
    }

    // 创建下载链接
    const url = window.URL.createObjectURL(blob)
    const link = document.createElement('a')

    link.href = url
    link.download = fileName
    link.style.display = 'none'
    document.body.appendChild(link)
    link.click()

    // 清理
    document.body.removeChild(link)
    window.URL.revokeObjectURL(url)

    message.success('代码下载成功')
  } catch (error: any) {
    console.error('下载失败:', error)

    // 根据错误类型提供更具体的错误信息
    if (error?.response?.status === 403) {
      message.error('无权限下载该应用代码')
    } else if (error?.response?.status === 404) {
      message.error('应用代码不存在，请先生成代码')
    } else if (error?.response?.status === 400) {
      message.error('应用ID无效')
    } else {
      message.error('下载失败，请稍后重试')
    }
  }
}

// 刷新预览
const refreshPreview = () => {
  if (!previewUrl.value) return

  isRefreshing.value = true
  // 强制刷新iframe
  const iframe = document.querySelector('.preview-iframe') as HTMLIFrameElement
  if (iframe) {
    iframe.src = iframe.src
  }
}

// iframe加载完成
const handleIframeLoad = () => {
  isRefreshing.value = false
  // 预览重新加载时，如处于编辑模式则重新注入并保持开启状态
  if (isEditMode.value) {
    editorController = null
    ensureEditor()
    editorController?.enable()
  }
}

// 新标签页打开
const openInNewTab = () => {
  if (previewUrl.value) {
    window.open(previewUrl.value, '_blank')
  }
}

// 分割条拖拽功能
const startDrag = (e: MouseEvent) => {
  // 在移动端禁用拖拽
  if (window.innerWidth <= 768) return

  isDragging.value = true
  startX.value = e.clientX
  startLeftWidth.value = leftWidth.value

  document.addEventListener('mousemove', onDrag)
  document.addEventListener('mouseup', stopDrag)
  document.body.style.cursor = 'col-resize'
  document.body.style.userSelect = 'none'

  // 防止选中文本
  e.preventDefault()
}

const onDrag = (e: MouseEvent) => {
  if (!isDragging.value) return

  // 取消之前的动画帧
  if (animationFrameId) {
    cancelAnimationFrame(animationFrameId)
  }

  // 使用requestAnimationFrame优化性能
  animationFrameId = requestAnimationFrame(() => {
    const deltaX = e.clientX - startX.value
    const containerWidth = window.innerWidth
    const deltaPercent = (deltaX / containerWidth) * 100

    const newLeftWidth = startLeftWidth.value + deltaPercent

    // 限制最小和最大宽度
    if (newLeftWidth >= 25 && newLeftWidth <= 75) {
      // 添加防抖机制：只有当变化超过0.5%或距离上次更新超过16ms时才更新
      const currentTime = performance.now()
      const widthDiff = Math.abs(newLeftWidth - dragCache.lastWidth)
      const timeDiff = currentTime - dragCache.lastUpdateTime

      if (widthDiff > 0.5 || timeDiff > 16) {
        leftWidth.value = newLeftWidth
        dragCache.lastWidth = newLeftWidth
        dragCache.lastUpdateTime = currentTime
      }
    }

    animationFrameId = null
  })
}

const stopDrag = () => {
  isDragging.value = false
  document.removeEventListener('mousemove', onDrag)
  document.removeEventListener('mouseup', stopDrag)
  document.body.style.cursor = ''
  document.body.style.userSelect = ''

  // 清理动画帧
  if (animationFrameId) {
    cancelAnimationFrame(animationFrameId)
    animationFrameId = null
  }

  // 重置拖拽缓存
  dragCache.lastWidth = leftWidth.value
  dragCache.lastUpdateTime = 0
}

// 组件挂载
onMounted(async () => {
  await fetchAppInfo()
  await loadChatHistory()
})

// 组件卸载时清理定时器
onUnmounted(() => {
  if (scrollTimeout.value) {
    clearTimeout(scrollTimeout.value)
  }
})
</script>

<style lang="scss" scoped>
.app-detail-page {
  height: 100vh;
  display: flex;
  flex-direction: column;
  background: #f5f5f5;
}

.top-bar {
  background: white;
  border-bottom: 1px solid #e8e8e8;
  padding: 20px 24px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);

  .left-section {
    display: flex;
    align-items: center;
    flex: 1;

    .app-info {
      flex: 1;

      .app-title-row {
        display: flex;
        align-items: center;
        gap: 12px;
        margin-bottom: 8px;

        .app-name {
          font-size: 24px;
          font-weight: 600;
          margin: 0;
          color: #333;
        }

        .app-status-tag {
          font-weight: 500;

          .anticon {
            margin-right: 4px;
          }
        }
      }

      .app-meta {
        display: flex;
        align-items: center;
        gap: 16px;

        .app-type {
          font-size: 13px;
          color: #666;
          background: #f5f5f5;
          padding: 2px 8px;
          border-radius: 12px;
        }

        .create-time {
          font-size: 13px;
          color: #999;
        }
      }
    }
  }

  .right-section {
    .deploy-btn {
      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
      border: none;

      &:hover {
        transform: translateY(-1px);
        box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
      }
    }

    .detail-btn {
      border: 1px solid #d9d9d9;

      &:hover {
        color: #667eea;
        border-color: #667eea;
        background: rgba(102, 126, 234, 0.05);
      }
    }

    .more-btn {
      border: 1px solid #d9d9d9;

      &:hover {
        color: #667eea;
        border-color: #667eea;
      }
    }
  }
}

.main-content {
  flex: 1;
  display: flex;
  min-height: 0;
  position: relative;
}

.chat-section {
  background: white;
  display: flex;
  flex-direction: column;
  min-width: 0;
  transition: width 0.1s ease-out;

  // 拖拽时禁用transition以提高性能
  &.dragging {
    transition: none !important;
  }
}

.messages-container {
  flex: 1;
  overflow-y: auto;
  padding: 24px;
  background: #fafafa;

  .load-more-wrapper {
    text-align: center;
    margin-bottom: 24px;

    .load-more-btn {
      color: #667eea;
      border: 1px solid rgba(102, 126, 234, 0.2);
      border-radius: 20px;

      &:hover {
        background: rgba(102, 126, 234, 0.1);
        border-color: #667eea;
      }
    }
  }

  .messages-list {
    .message-item {
      display: flex;
      margin-bottom: 32px;
      align-items: flex-start;

      &.user-message {
        flex-direction: row-reverse;

        .message-content {
          background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
          color: white;
          margin-right: 12px;
          border-radius: 20px 20px 4px 20px;

          .message-header {
            .sender-name {
              color: rgba(255, 255, 255, 0.9);
            }

            .message-time {
              color: rgba(255, 255, 255, 0.7);
            }
          }
        }
      }

      &.ai-message {
        .message-content {
          background: white;
          color: #333;
          margin-left: 12px;
          border-radius: 20px 20px 20px 4px;
          border: 1px solid #e8e8e8;

          .message-header {
            .sender-name {
              color: #667eea;
            }
          }
        }
      }

      .message-avatar {
        flex-shrink: 0;

        .user-avatar {
          background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
          border: 2px solid white;
          box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3);
        }

        .ai-avatar {
          background: #f0f0f0;
          color: #667eea;
          border: 2px solid white;
          box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
        }
      }

      .message-content {
        max-width: 75%;
        padding: 16px 20px;
        box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);

        .message-header {
          display: flex;
          justify-content: space-between;
          align-items: center;
          margin-bottom: 8px;

          .sender-name {
            font-size: 13px;
            font-weight: 500;
          }

          .message-time {
            font-size: 11px;
            opacity: 0.7;
          }
        }

        .message-text {
          line-height: 1.6;
          word-break: break-word;
          font-size: 14px;
          position: relative;

          .ai-message-content {
            // Markdown渲染样式由MarkdownRenderer组件处理
          }

          .streaming-text {
            display: inline;
          }

          .typing-cursor {
            display: inline-block;
            animation: blink 1s infinite;
            color: #667eea;
            font-weight: bold;
            margin-left: 2px;
          }
        }
      }
    }
  }

  .empty-messages {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 50%;

    .empty-content {
      text-align: center;
      color: #999;

      .empty-icon {
        font-size: 48px;
        margin-bottom: 16px;
        color: #ddd;
      }

      p {
        margin: 0;
        font-size: 16px;
      }
    }
  }
}

.input-section {
  border-top: 1px solid #e8e8e8;
  padding: 20px;

  .input-container {
    background: #f8f9fa;
    border-radius: 12px;
    padding: 12px;
    border: 1px solid #e8e8e8;

    .message-input {
      border: none;
      background: transparent;
      resize: none;

      &:focus {
        box-shadow: none;
      }
    }

    .input-actions {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-top: 12px;

      .char-count {
        font-size: 12px;
        color: #999;
      }

      .button-group {
        display: flex;
        gap: 8px;
        align-items: center;
      }

      .edit-btn {
        border: 1px solid #d9d9d9;

        &:hover:not(:disabled) {
          color: #667eea;
          border-color: #667eea;
        }
      }

      .send-btn {
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        border: none;

        &:hover:not(:disabled) {
          transform: translateY(-1px);
          box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
        }
      }
    }
  }
}

.selected-el-desc {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 6px 10px;
  align-items: baseline;

  .row {
    display: contents;
  }

  .label {
    color: #666;
    font-size: 12px;
    background: #f5f5f5;
    border-radius: 4px;
    padding: 0 6px;
  }

  .code {
    background: #f6f8fa;
    padding: 2px 6px;
    border-radius: 4px;
    border: 1px solid #e1e4e8;
    font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
    font-size: 12px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .content {
    font-size: 12px;
    color: #333;
  }
}

// 分割条样式
.splitter {
  width: 6px;
  background: #f0f0f0;
  cursor: col-resize;
  position: relative;
  transition: background-color 0.2s ease;
  border-left: 1px solid #e8e8e8;
  border-right: 1px solid #e8e8e8;
  flex-shrink: 0;

  &:hover {
    background: #e6f7ff;
  }

  &.dragging {
    background: #1890ff;
  }

  &::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 2px;
    height: 20px;
    background: #d9d9d9;
    border-radius: 1px;
    transition: background-color 0.2s ease;
  }

  &:hover::after {
    background: #1890ff;
  }

  &.dragging::after {
    background: white;
  }
}

.preview-section {
  background: white;
  display: flex;
  flex-direction: column;
  min-width: 300px;
  transition: width 0.1s ease-out;

  // 拖拽时禁用transition以提高性能
  &.dragging {
    transition: none !important;
  }
}

.preview-header {
  padding: 24px 24px 16px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  border-bottom: 1px solid #f0f0f0;
  background: #fafafa;

  h3 {
    margin: 0;
    font-size: 16px;
    font-weight: 600;
    color: #333;
    display: flex;
    align-items: center;
    gap: 8px;

    &::before {
      content: '';
      width: 8px;
      height: 8px;
      border-radius: 50%;
      background: #52c41a;
      display: inline-block;
    }
  }

  .preview-actions {
    display: flex;
    gap: 8px;

    .refresh-btn,
    .external-btn {
      color: #666;
      border: 1px solid #d9d9d9;
      border-radius: 6px;

      &:hover {
        color: #667eea;
        border-color: #667eea;
        background: rgba(102, 126, 234, 0.05);
      }
    }
  }
}

.preview-content {
  flex: 1;
  margin: 0;
  border: none;
  border-radius: 0;
  overflow: hidden;
  position: relative;
  background: #f5f5f5;

  .preview-placeholder {
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #fafafa;

    .placeholder-content {
      text-align: center;
      color: #999;

      .placeholder-icon {
        font-size: 64px;
        margin-bottom: 24px;
        color: #ddd;
      }

      p {
        margin: 8px 0;
        font-size: 16px;

        &.placeholder-hint {
          font-size: 14px;
          color: #bbb;
          margin-top: 8px;
        }
      }
    }
  }

  .preview-iframe {
    width: 100%;
    height: 100%;
    border: none;
    background: white;
  }

  .drag-overlay {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: transparent;
    z-index: 1000;
    cursor: col-resize;
  }

  .generating-overlay {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(255, 255, 255, 0.95);
    backdrop-filter: blur(4px);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;

    .ant-spin {
      margin-bottom: 16px;
    }

    p {
      margin: 0;
      color: #666;
      font-size: 14px;
    }
  }
}

@keyframes blink {
  0%,
  50% {
    opacity: 1;
  }
  51%,
  100% {
    opacity: 0;
  }
}

// 响应式设计
@media (max-width: 768px) {
  .main-content {
    flex-direction: column;
  }

  .chat-section {
    width: 100% !important;
    height: 60vh;
  }

  .splitter {
    display: none;
  }

  .preview-section {
    width: 100% !important;
    height: 40vh;
    min-width: auto;
  }

  .top-bar {
    padding: 16px;
    flex-direction: column;
    align-items: flex-start;
    gap: 16px;

    .left-section {
      width: 100%;
      gap: 12px;

      .app-info {
        .app-title-row {
          flex-direction: column;
          align-items: flex-start;
          gap: 8px;

          .app-name {
            font-size: 20px;
          }
        }

        .app-meta {
          gap: 12px;
        }
      }
    }

    .right-section {
      width: 100%;

      :deep(.ant-space) {
        width: 100%;
        justify-content: space-between;
      }
    }
  }

  .messages-container {
    padding: 16px;
  }

  .input-section {
    padding: 16px;
  }
}

// 应用详情弹窗样式
:deep(.app-detail-modal) {
  .ant-modal-header {
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    border-bottom: none;

    .ant-modal-title {
      color: white;
      font-weight: 600;
    }
  }

  .ant-modal-close {
    .ant-modal-close-x {
      color: white;

      &:hover {
        color: rgba(255, 255, 255, 0.8);
      }
    }
  }
}

.detail-content {
  .app-name-text {
    font-size: 16px;
    font-weight: 600;
    color: #333;
  }

  .preview-link {
    color: #667eea;
    text-decoration: none;
    display: flex;
    align-items: center;
    gap: 6px;

    &:hover {
      color: #764ba2;
      text-decoration: underline;
    }
  }

  .app-description,
  .init-prompt {
    background: #f8f9fa;
    padding: 12px;
    border-radius: 6px;
    border: 1px solid #e8e8e8;
    line-height: 1.6;
    max-height: 120px;
    overflow-y: auto;
    white-space: pre-wrap;
    word-break: break-word;
  }

  .stats-section {
    margin-top: 24px;
    padding-top: 20px;
    border-top: 1px solid #f0f0f0;

    h4 {
      margin-bottom: 16px;
      color: #333;
      font-weight: 600;
    }

    .ant-statistic {
      text-align: center;

      .ant-statistic-title {
        color: #666;
        font-size: 13px;
      }

      .ant-statistic-content {
        color: #667eea;
        font-weight: 600;
      }
    }
  }
}
</style>
